﻿// Inherit custom: http://geekswithblogs.net/lbugnion/archive/2007/03/02/107747.aspx
// Design mode: http://blogs.msdn.com/jnak/archive/2006/10/07/Detecting-Design-Mode.aspx

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using WinForms = System.Windows.Forms;
using Microsoft.Win32;
using System.Reflection;

namespace WpfAppHost
{
    /// <summary>
    /// Interaction logic for ApplicationWindow.xaml
    /// </summary>
    public partial class ApplicationWindow : Window
    {
        bool showHiddenMessage = true;
        bool hideOnClose = true, userQuitting = false;
        bool designMode;
        string appName = "Application";
        WinForms.NotifyIcon _trayNotifyIcon = new System.Windows.Forms.NotifyIcon();

        public ApplicationWindow()
        {
            // Visual Studio creates an instance for the Designer window.  We don't want
            // a tray icon from a Designer instance!
            designMode = System.ComponentModel.DesignerProperties.GetIsInDesignMode(this);

            if (!designMode)
            {
                BuildContextMenu();

                // Create event handlers for the window (save/restore size/location)
                this.Initialized += new EventHandler(ApplicationWindow_Initialized);
                this.SizeChanged += new SizeChangedEventHandler(ApplicationWindow_SizeChanged);
                this.LocationChanged += new EventHandler(ApplicationWindow_LocationChanged);
                this.Closing += new System.ComponentModel.CancelEventHandler(ApplicationWindow_Closing);
            }
        }

        private void BuildContextMenu()
        {
            // TODO: Pull menu code into a real designer
            WinForms.ContextMenu cm = new WinForms.ContextMenu();

            // Ugly manual menu creation
            WinForms.MenuItem mi = cm.MenuItems.Add("Show Settings");
            mi.DefaultItem = true;
            mi.Click += (o, e) =>
            {
                ShowWindow();
            };

            mi = cm.MenuItems.Add("-");

            mi = cm.MenuItems.Add("Start with Windows");
            mi.Name = "StartupCommand";
            mi.Click += (o, e) => { ToggleWindowsStartup(); };
            mi.Checked = GetWindowsStartupState();

            mi = cm.MenuItems.Add("Exit");
            mi.Click += (o, e) => { userQuitting = true; Application.Current.Shutdown(); };

            // Initializes NotifyIcon for icon, men, and text
            _trayNotifyIcon.Icon = Properties.Resources.DefaultTrayIcon;
            _trayNotifyIcon.ContextMenu = cm;
            _trayNotifyIcon.Text = appName;
            _trayNotifyIcon.DoubleClick += (o, e) =>
            {
                ShowWindow();
            };
        }

        private void ToggleWindowsStartup()
        {
            using (RegistryKey hkcu = Registry.CurrentUser)
            {
                using (RegistryKey runKey =
                    hkcu.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true))
                {
                    object appVal = runKey.GetValue(appName);

                    WinForms.MenuItem mi = TrayIconMenu.MenuItems["StartupCommand"];

                    if (appVal == null)
                    {
                        runKey.SetValue(appName, Assembly.GetEntryAssembly().Location);
                        mi.Checked = true;
                    }
                    else
                    {
                        runKey.DeleteValue(appName);
                        mi.Checked = false;
                    }
                }
            }
        }

        private bool GetWindowsStartupState()
        {
            using (RegistryKey hkcu = Registry.CurrentUser)
            {
                using (RegistryKey runKey =
                    hkcu.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true))
                {
                    object runVal = runKey.GetValue(appName);

                    if (runVal == null) return false;
                    else return true;
                }
            }
        }

        /// <summary>
        /// Restores window when app is initialized
        /// </summary>
        void ApplicationWindow_Initialized(object sender, EventArgs e)
        {
            RestoreWindowState();
        }

        /// <summary>
        /// Handles SizeChanged event for the window
        /// </summary>
        void ApplicationWindow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            SaveWindowState();
        }

        /// <summary>
        /// Handles SizeChanged event for the window
        /// </summary>
        void ApplicationWindow_LocationChanged(object sender, EventArgs e)
        {
            SaveWindowState();
        }

        /// <summary>
        /// Gets or sets a value that indicates whether the close button should send
        /// the application to tray (true) or exit (false).
        /// </summary>
        public bool HideOnClose
        {
            get { return hideOnClose; }
            set
            {
                hideOnClose = value;
            }
        }

        /// <summary>
        /// Handles Closing event for the window and determines if the application should hide or close
        /// </summary>
        void ApplicationWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (hideOnClose && !userQuitting)
            {
                e.Cancel = true;
                if (showHiddenMessage)
                {
                    _trayNotifyIcon.Click += (o, e2) => { showHiddenMessage = false; };
                    _trayNotifyIcon.ShowBalloonTip(10000, appName + " - " + "Minimized",
                        appName + " has been minimized to the tray.  Click this message to hide this message in the future.",
                        System.Windows.Forms.ToolTipIcon.Info);
                }
                HideWindow();
            }
            else
            {
                _trayNotifyIcon.Visible = false;
                SaveWindowState();
            }
        }

        protected void HideWindow()
        {
            this.ShowInTaskbar = false;
            this.Hide();
        }

        protected void ShowWindow()
        {
            this.ShowInTaskbar = true;
            this.Show();
            this.Focus();
        }

        /// <summary>
        /// Saves position and size information to application settings
        /// </summary>
        protected void SaveWindowState()
        {
            if (this.WindowState == WindowState.Normal)
            {
                Properties.Settings.Default.LastWindowPosition =
                    new System.Drawing.Point((int)this.Left, (int)this.Top);
                Properties.Settings.Default.LastWindowSize =
                    new System.Drawing.Size((int)this.Width, (int)this.Height);
                Properties.Settings.Default.Save();
            }
        }

        /// <summary>
        /// Reads Restores the window size/location from application settings
        /// </summary>
        protected void RestoreWindowState()
        {
            this.Left = Properties.Settings.Default.LastWindowPosition.X;
            this.Top = Properties.Settings.Default.LastWindowPosition.Y;
            this.Width = Properties.Settings.Default.LastWindowSize.Width;
            this.Height = Properties.Settings.Default.LastWindowSize.Height;
        }

        /// <summary>
        /// Sets the name of the application.  Used by the window title and NotifyIcon
        /// </summary>
        public string ApplicationName
        {
            get { return appName; }
            set
            {
                appName = value;
                this.Title = value;
                _trayNotifyIcon.Text = value;
            }
        }

        /// <summary>
        /// Displays a status message using a NotifyIcon balloon tip
        /// </summary>
        /// <param name="title"></param>
        /// <param name="msg"></param>
        public void ShowBalloonMessage(string title, string msg)
        {
            _trayNotifyIcon.ShowBalloonTip(10000, appName + " - " + title, msg,
                System.Windows.Forms.ToolTipIcon.Info);
        }

        /// <summary>
        /// Gets or sets a value indicating whether the window should
        /// show a notification icon in the system tray.
        /// </summary>
        public bool ShowTrayIcon
        {
            get
            {
                return _trayNotifyIcon.Visible;
            }
            set
            {
                appName = Title;
                _trayNotifyIcon.Text = appName;
                _trayNotifyIcon.Visible = value;
            }
        }

        /// <summary>
        /// Gets or sets the Icon used by the application NotifyIcon
        /// </summary>
        public Icon TrayIcon
        {
            get
            {
                return _trayNotifyIcon.Icon;
            }
            set
            {
                _trayNotifyIcon.Icon = value;
            }
        }

        /// <summary>
        /// Gets or sets the menu used by the application NotifyIcon
        /// </summary>
        public WinForms.ContextMenu TrayIconMenu
        {
            get
            {
                return _trayNotifyIcon.ContextMenu;
            }
            set
            {
                _trayNotifyIcon.ContextMenu = value;
            }
        }
    }
}
